package delphorm.service.questionnaire;

import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import delphorm.entite.personne.Utilisateur;
import delphorm.entite.questionnaire.IConstantesEtatQuestionnaire;
import delphorm.entite.questionnaire.InstanceQuestion;
import delphorm.entite.questionnaire.InstanceQuestionnaire;
import delphorm.entite.questionnaire.InstanceReponse;
import delphorm.entite.questionnaire.InstanceReponseOuverte;
import delphorm.entite.questionnaire.Question;
import delphorm.entite.questionnaire.Questionnaire;
import delphorm.entite.questionnaire.Reponse;
import delphorm.entite.questionnaire.ReponseFermee;
import delphorm.entite.questionnaire.ValeurFichier;
import delphorm.service.exception.ServiceException;
import delphorm.utils.RandomGeneratorUtils;

/**
 * Classe de service bouchonnée Gére les questionnaires et les instances de
 * questionnaire dans une map
 * 
 * @author jerome
 * 
 */
public class BouchonQuestionnaire implements IQuestionnaire {

	/**
	 * Map qui contient le jeu de données de questionnaires
	 */
	Map<Long, Questionnaire> questionnaires = new HashMap<Long, Questionnaire>();

	/**
	 * Map qui contient le jeu de données des instances de questionnaire
	 */
	Map<Long, InstanceQuestionnaire> instancesQuestionnaire = new HashMap<Long,InstanceQuestionnaire>();

	/**
	 * @return Le jeu de donnée des instances de questionnaire
	 */
	public Map<Long, InstanceQuestionnaire> getInstancesQuestionnaire() {
		return instancesQuestionnaire;
	}

	/**
	 * Setter du jeu de donnée des instances de questionnaire
	 * 
	 * @param instancesQuestionnaire
	 *            Jeu de donnée à définir
	 */
	public void setInstancesQuestionnaire(
			Map<Long, InstanceQuestionnaire> instancesQuestionnaire) {
		this.instancesQuestionnaire = instancesQuestionnaire;
	}

	/**
	 * @return La map qui contient le jeu de données
	 */
	public Map<Long, Questionnaire> getQuestionnaires() {
		return questionnaires;
	}

	/**
	 * @param questionnaires
	 *            Jeu de données à définir
	 */
	public void setQuestionnaires(Map<Long, Questionnaire> questionnaires) {
		this.questionnaires = questionnaires;
	}

	/**
	 * Génère un identifiant de questionnaire aléatoirement
	 * 
	 * @return L'identifiant généré aléatoirement
	 */
	private Long genererIdentifiantQuestionnaire() {
		return RandomGeneratorUtils.genererIdentifiant(questionnaires);
	}

	private Long genererIdentifiantInstanceQuestionnaire() {
		return RandomGeneratorUtils.genererIdentifiant(instancesQuestionnaire);
	}

	

	public InstanceQuestionnaire enregistrerInstanceQuestionnaire(
			InstanceQuestionnaire instanceQuestionnaire) {
		instanceQuestionnaire.setEtat(new Character('O'));
		return enregistrerInstanceQuestionnaireGenerique(instanceQuestionnaire);
	}

	public InstanceQuestionnaire enregistrerInstanceQuestionnairePartiel(
			InstanceQuestionnaire instanceQuestionnaire) {
		instanceQuestionnaire.setEtat(new Character('C'));
		return enregistrerInstanceQuestionnaireGenerique(instanceQuestionnaire);
	}

	/**
	 * Enregistrement générique
	 * 
	 * @param instanceQuestionnaire
	 *            Instance de questionnaire à enregistrer
	 * @return
	 */
	private InstanceQuestionnaire enregistrerInstanceQuestionnaireGenerique(
			InstanceQuestionnaire instanceQuestionnaire) {
		if (instanceQuestionnaire.getId() == null)
			instanceQuestionnaire
					.setId(genererIdentifiantInstanceQuestionnaire());
		// enregistre dans la Map
		instancesQuestionnaire.put(instanceQuestionnaire.getId(),
				instanceQuestionnaire);
		return instanceQuestionnaire;
	}

	public Questionnaire enregistrerQuestionnaire(Questionnaire questionnaire) {
		// met la date de modification à la date courante
		questionnaire.setDateModification(new Date());
		// met le questionnaire à l'état travail
		questionnaire.setEtat(IConstantesEtatQuestionnaire.TRAVAIL);
		return enregistrerQuestionnaireGenerique(questionnaire);
	}

	/**
	 * Enregistrement générique du questionnaire
	 * 
	 * @param questionnaire
	 *            Le questionnaire à enregistrer
	 * @return Le questionnaire enregistré
	 */
	private Questionnaire enregistrerQuestionnaireGenerique(
			Questionnaire questionnaire) {
		if (questionnaire.getId() == null)
			questionnaire.setId(genererIdentifiantQuestionnaire());
		// enregistre dans la Map
		questionnaires.put(questionnaire.getId(), questionnaire);
		return questionnaire;
	}

	public InstanceQuestionnaire getInstanceQuestionnaireParId(Long id) {
		if (instancesQuestionnaire.containsKey(id))
			return instancesQuestionnaire.get(id);
		return null;
	}

	/**
	 * @inheritDoc Recherche dans la map les instances de questionnaire dont le
	 *             questionnaire associé a l'identifiant passé en paramètre
	 */
	public List<InstanceQuestionnaire> getInstancesQuestionnaireParQuestionnaireId(
			Long numeroQuestionnaire) {
		List<InstanceQuestionnaire> liste = new ArrayList<InstanceQuestionnaire>();
		for (Iterator<InstanceQuestionnaire> it = instancesQuestionnaire
				.values().iterator(); it.hasNext();) {
			InstanceQuestionnaire instanceQuestionnaire = it.next();
			if (instanceQuestionnaire.getQuestionnaire().getId().equals(
					numeroQuestionnaire))
				liste.add(instanceQuestionnaire);
		}
		return liste;
	}

	/**
	 * @inheritDoc Recherche dans la map des instances ceux qui sont liés à l'id
	 *             de l'utilisateur passé en paramètre
	 */
	public List<InstanceQuestionnaire> getInstancesQuestionnaireEnCoursParUtilisateur(
			Utilisateur utilisateur) {
		List<InstanceQuestionnaire> liste = new ArrayList<InstanceQuestionnaire>();
		for (Iterator<InstanceQuestionnaire> it = instancesQuestionnaire
				.values().iterator(); it.hasNext();) {
			InstanceQuestionnaire instanceQuestionnaire = it.next();
			if (instanceQuestionnaire.getAuteur().getId().equals(
					utilisateur.getId()))
				liste.add(instanceQuestionnaire);
		}
		return liste;

	}

	/**
	 * @inheritDoc Recherche dans la map le questionnaire.
	 */
	public Questionnaire getQuestionnaireParId(Long id) {
		return questionnaires.get(id);
	}

	/**
	 * Recherche dans les maps questionnaires et instances de questionnaires
	 * toutes le fichier qui correspond
	 * 
	 * @inheritDoc
	 */
	public ValeurFichier getValeurFichier(Long idFichier) {
		// recherche dans les instances
		for (InstanceQuestionnaire instanceQuestionnaire : instancesQuestionnaire
				.values()) {
			for (InstanceQuestion instanceQuestion : instanceQuestionnaire
					.getInstancesQuestion()) {
				for (InstanceReponse instanceReponse : instanceQuestion
						.getInstancesReponse()) {
					if (instanceReponse instanceof InstanceReponseOuverte) {
						InstanceReponseOuverte instanceReponseOuverte = (InstanceReponseOuverte) instanceReponse;
						if (instanceReponseOuverte.getValeur() instanceof ValeurFichier) {
							ValeurFichier valeurFichier = (ValeurFichier) instanceReponseOuverte
									.getValeur();
							if (valeurFichier.getId().equals(idFichier))
								return valeurFichier;
						}
					}
				}
			}
		}
		// recherche dans les questionnaires
		for (Questionnaire questionnaire : questionnaires.values()) {
			for (Question question : questionnaire.getQuestions()) {
				for (Reponse reponse : question.getReponses()) {
					if (reponse instanceof ReponseFermee) {
						ReponseFermee reponseFermee = (ReponseFermee) reponse;
						if (reponseFermee.getValeur() instanceof ValeurFichier) {
							ValeurFichier valeurFichier = (ValeurFichier) reponseFermee
									.getValeur();
							if (valeurFichier.getId().equals(idFichier))
								return valeurFichier;
						}
					}
				}
			}
		}

		return null;

	}

	/**
	 * @inheritDoc
	 */
	public List<Questionnaire> listerQuestionnairesEnPublication() {
		List<Questionnaire> liste = new ArrayList<Questionnaire>();
		for (Questionnaire questionnaire : questionnaires.values()) {
			if (questionnaire.getEtat().equals(
					IConstantesEtatQuestionnaire.PUBLIE))
				liste.add(questionnaire);
		}
		return liste;
	}

	public List<Questionnaire> listerQuestionnairesTous(String trier) {
		// FIXME trier la list
		return new ArrayList<Questionnaire>(questionnaires.values());
	}

	public List<Questionnaire> listerQuestionnairesUtilisateur(
			Utilisateur utilisateur, String trier) {
		// FIXME trier la liste
		List<Questionnaire> liste = new ArrayList<Questionnaire>();
		for (Questionnaire questionnaire : questionnaires.values()) {
			if (questionnaire.getAuteur().getId().equals(utilisateur.getId()))
				liste.add(questionnaire);
		}
		return liste;
	}

	private Questionnaire chercherQuestionnaire(Long idQuestionnaire) throws ServiceException
	{
		Questionnaire questionnaire = getQuestionnaireParId(idQuestionnaire);
		if (questionnaire == null) {
			String[] args = { idQuestionnaire.toString() };
			throw new ServiceException("Questionnaire " + idQuestionnaire
					+ " non trouvé", null, this.getClass().getCanonicalName(),
					"chercherQuestionnaire", args);
		}
		return questionnaire;
	}
	public void mettreQuestionnaireEnPerime(Long idQuestionnaire) throws ServiceException {
		Questionnaire questionnaire = chercherQuestionnaire(idQuestionnaire);
		questionnaire.setEtat(IConstantesEtatQuestionnaire.PERIME);
		questionnaire.setDateModification(new Date());
		questionnaire.setDatePeremption(new Date());

	}

	public void mettreQuestionnaireEnPublication(Long idQuestionnaire) throws ServiceException {
		Questionnaire questionnaire = chercherQuestionnaire(idQuestionnaire);
		questionnaire.setEtat(IConstantesEtatQuestionnaire.PUBLIE);
		questionnaire.setDateModification(new Date());
		questionnaire.setDatePeremption(new Date());
	}

	public void mettreQuestionnaireEnTest(Long idQuestionnaire) throws ServiceException {
		Questionnaire questionnaire = chercherQuestionnaire(idQuestionnaire);
		questionnaire.setEtat(IConstantesEtatQuestionnaire.TEST);
		questionnaire.setDateModification(new Date());
		questionnaire.setDatePeremption(new Date());

	}

	public void mettreQuestionnaireEnTravail(Long idQuestionnaire) throws ServiceException {
		Questionnaire questionnaire = chercherQuestionnaire(idQuestionnaire);
		questionnaire.setEtat(IConstantesEtatQuestionnaire.TRAVAIL);
		questionnaire.setDateModification(new Date());
		questionnaire.setDatePeremption(new Date());

	}

	public InstanceQuestionnaire nouveauInstanceQuestionnaire(
			Questionnaire questionnaire, Utilisateur auteur) {
		InstanceQuestionnaire iQ = new InstanceQuestionnaire();
		iQ.setAuteur(auteur);
		iQ.setDateRemplissage(new Date());
		iQ.setQuestionnaire(questionnaire);
		return iQ;
	}

	public Questionnaire nouveauQuestionnaire(Utilisateur u) {
		Questionnaire questionnaire = new Questionnaire();
		questionnaire.setAuteur(u);
		questionnaire.setDateCreation(new Date());
		questionnaire.setDateModification(new Date());
		questionnaire.setEtat(IConstantesEtatQuestionnaire.TRAVAIL);
		
		return questionnaire;
	}

	public void supprimerQuestionnaire(Long id) {
		questionnaires.remove(id);
	}

}
